22 Aug 2018 • 16 minute read Most of the English-speaking world has Amazon and eBay. In New Zealand we have TradeMe - an online auction & classified advert website where Kiwis go to buy & sell general items, cars, and property. If the numbers are to be believed, then pretty much every Kiwi has a TradeMe account. I don’t think it’s an understatement to say that TradeMe is an itegral part of modern New Zealand culture.
Back in 2016, TradeMe announced that it was working on a new “smartphone-optimised” responsive website that will eventually also replace the desktop website. Then halfway through 2018, they announced that the new responsive website was being rolled out to real users.
Being the ever-curious developer, I wanted to give the new TradeMe website a try. After a couple of weeks using the new website on my phone (a Nokia 7 Plus), I became frustrated with how much time I spent staring at a loading spinner, and how sluggish the UI interactions were. So I went back to the old website.
This bothered me, because I know that the other TradeMe experiences are fast. Why should this new website be so slow? I wanted to dig deeper, so I’ve taken the opportunity to conduct a detailed performance review.
(Read more) 5 Aug 2017 • 6 minute read TL;DR
- Second is a framework for building React applications where the data is fetched on the server and most of the components do not change after the first render.
- Components can declare their data dependencies using a container similar to Facebook’s Relay.
- By default components are only rendered on the server; client-side rendering is opt-in by using the component dehydrator.
- Second works with any React-like library including Preact.
Why build this framework?
While using React to build the BBC News front page and several other mostly-static pages, a common theme emerged: only a small number of components on these pages require client-side JavaScript to function. Rendering every component in the browser does not provide an optimal experience — especially for users on low-powered devices or low-speed connections. Instead, selectively bundling components for the browser reduces bundle sizes and minimizes CPU overhead without sacrificing React’s event system and stateful components.
Second is not a large or complex framework. It is the result of combining several simple and well-tested techniques—
- Server-side rendering
- Container components for declarative data requirements
- Selective client-side rendering
—and combining them into a single package that can be easily reused across multiple applications.
(Read more) 16 Feb 2017 • 2 minute read I started 2016 feeling quite overwhelmed by the sheer number of new technologies that were being introduced. This year I feel like many of those technologies have matured, so I have collated a list of the ones that I think deserve your attention. My focus for the last couple of years has been on performance, so I’ve made an effort to ensure that all of the technologies mentioned are either “performance-friendly” or are directly related to performance.
(Read more) 1 Oct 2013 • 1 minute read Using Node.js* you can run a simple “HTTP status as a service” server. This can be useful for quickly checking whether your application handles various status codes.
var http = require('http');
http.createServer(function (request, response) {
var status = request.url.substr(1);
if ( ! http.STATUS_CODES[status]) {
status = '404';
}
response.writeHead(status, { 'Content-Type': 'text/plain' });
response.end(http.STATUS_CODES[status]);
}).listen(process.env.PORT || 5000);
This will create a server on port 5000, or any port that you specify in the PORT
environment variable. It will respond to /{CODE}
and return the HTTP status that corresponds to {CODE}
. Here’s a couple of examples:
$ curl -i http://127.0.0.1:5000/500
HTTP/1.1 500 Internal Server Error
Content-Type: text/plain
Date: Mon, 30 Sep 2013 14:10:10 GMT
Connection: keep-alive
Transfer-Encoding: chunked
Internal Server Error%
$ curl -i http://127.0.0.1:5000/404
HTTP/1.1 404 Not Found
Content-Type: text/plain
Date: Mon, 30 Sep 2013 14:10:32 GMT
Connection: keep-alive
Transfer-Encoding: chunked
Not Found%
This is a really simple example, and could easily be extended to let you specify a Location
header value for 30X responses.
*Well, you could use anything really. I’m just using Node.js since JavaScript is my language of choice.
(Read more) 7 Sep 2013 • 1 minute read There’s a fairly quick way to convert Bootswatch themes to Sass (which you might want to do if you use something like sass-bootstrap).
Simply download the theme’s variables.less and run the following find/replace patterns against it:
Variables
Find (regex): @([a-zA-Z0-9_-]+)
Replace: \$$1
Mixins
Find: spin(
Replace: adjust-hue(
This is all I’ve found in the themes that I’ve tried.
(Read more) 21 May 2013 • 7 minute read Inspired by Eric Mann’s post on caching WordPress with Redis, I thought I’d experiment with a similar setup using Memcached. Any in-memory caching system should work just as well, but I’ve chosen Memcached because it’s already running on my server and because PHP already has a built-in libmemcached API.
My current setup is Nginx and PHP-FPM, with WP Super Cache. The cache is saved to the filesystem, allowing Nginx to serve static files (which it is very good at) without needing to pass any requests to PHP. This setup has worked very well, so I’ll be using it as a baseline.
To use Memcached, every request needs to be passed to PHP. My gut feeling was that this would be slower than serving static files with Nginx due to the overhead of spinning up a PHP process for each request.
Benchmarks
To find out which of the two setups was faster, I measured the following metrics using WebPagetest and Blitz (referral link):
(Read more) 15 Nov 2012 • 1 minute read Setting up your editor correctly can make working with other developers much less painful. Below are some things that I believe every developer should do when editing source code. Any good IDE or editor should have settings to do these things automatically - the points below are paired with their Sublime Text setting.
- Trim trailing whitespace -
"trim_trailing_white_space_on_save": true
- Always use Unix line endings (LF) -
"default_line_ending": "unix"
- Ensure files end with a new line -
"ensure_newline_at_eof_on_save": true
- Automatically detect indentation style -
"detect_indentation": true
- Or, failing the above, have a way to quickly switch between indentation styles.
(Read more) 13 Sep 2012 • 1 minute read Coming from PhpStorm (a full-featured IDE), I felt that Sublime Text was missing a few useful features. Luckily, one of the great things about Sublime is that it can be easily extended with plugins and packages. Perhaps the most useful package for Sublime is Sublime Package Control, which allows you to easily install and manage packages (it can even uninstall itself - über meta).
Below are some Sublime Text packages that I have found to be useful for web development.
(Read more) 1 Jul 2012 • 2 minute read Bcrypt is a Blowfish-based hashing algorithm which is commonly used for password hashing because of its potentially expensive key setup phase. A Bcrypt hash has the following structure:
$2a$(2 chars work)$(22 chars salt)(31 chars hash)
The reason that the key setup phase can be potentially expensive is because it is run 2
times. As password hashing is usually associated with common tasks like logging a user into a system, it’s important to find the right balance between security and performance. Using a high work factor makes it incredibly difficult to execute a brute-force attack, but can put unnecessary load on the system.
Using Marco Arment’s PHP Bcrypt class, I performed some benchmarks to determine how long it takes to hash a string with various work factors:
(Read more) 17 Nov 2011 • 4 minute read Unlike Doctrine 1 with it’s NestedSet behaviour, there is no nested set functionality in the core of Doctrine 2. There are a few extensions available that offer nested set support:
I tried all of these extensions, but none of them felt simple or lightweight enough for my application. What I wanted to do was have a Category entity which could have a tree of sub-categories, e.g:
(Read more) 23 Jul 2011 • 2 minute read Setting up a web server with Apache, PHP, and MySQL on any Debian-based system is really easy thanks to APT (Advanced Packaging Tool). Follow along and you’ll have a web server set up within fifteen minutes.
(Read more) 25 Jun 2011 • 1 minute read It’s debatable whether or not it’s good practice to use short syntax in PHP. I personally prefer to use short syntax because it keeps my view files looking tidy.
The regular expression below will find all one-liner print
and echo
statements (e.g. <?php print $var; ?>
) and convert them to <?= $var ?>
statements. It will not match statements containing closing brackets, for example when using ternary operators: <?= ($foo == $bar) ? 'Foobar' : 'Foo' ?>
Find:
<\?php[\s]*(print|echo)[\s]*\(?([^>\)]+?)\)?[\s]*;?[\s]*\?>
(Read more) 9 Jan 2011 • 3 minute read Doctrine 2’s console is really powerful when you know how to use it. You can generate entity classes and their method stubs, reverse-engineer a database, validate your entity schemas, and much more. In this post, I’m going to cover some of the Doctrine console’s more useful commands and explain how you can use them to reduce development time. For a full overview of the Doctrine 2 console, read the Doctrine Tools documentation.
(Read more) 13 Nov 2010 • 1 minute read A word of warning: eAccelerator does not play well with Doctrine 2. This came to my attention today after I installed eAccelerator so that I could measure the performance gains (if any). As it turns out, one of eAccelerator’s “features” is to remove DocBlocks from PHP scripts - probably to reduce compile times. Suddenly my application was throwing exceptions with the message “Class X is not a valid entity or mapped super class”.
(Read more) 9 Nov 2010 • 4 minute read My latest CodeIgniter 2 project requires that I use query strings in some of my URLs. CodeIgniter 1 was notoriously difficult to work with when you enabled query strings, and unfortunately CodeIgniter 2 is no different. Whereas in CodeIgniter 1 you could change two configuration options to enable a combination of segment-based URLs and query strings, this same approach only makes matters worse in CodeIgniter 2.
(Read more) 5 Oct 2010 • 4 minute read This post assumes you have set up Doctrine 2 with CodeIgniter 2.
Load Data from Fixtures
I could not find a command to load data from fixtures, so I made a very basic command that recursively executes native SQL. If you want to load data from YAML files, you will need to search elsewhere for a YAML interpreter or even a way to convert YAML to SQL.
(Read more) 26 Sep 2010 • 11 minute read If you’re looking for a quick way to get Doctrine 2 running with CodeIgniter 2, you might want to download my CodeIgniter 2/Doctrine 2 package
Overview
CodeIgniter is a great PHP framework. The codebase is clean, the documentation is fantastic, and it’s regularly updated. Doctrine is a good ORM for the same reasons: it’s very well-written, has extensive documentation, and is actively developed. A combination of these two systems makes it easy to build database-oriented web applications quicker than ever before.
To get started, download CodeIgniter 2 and Doctrine 2 – make sure you use the ‘Download Archive’ link when downloading Doctrine.
(Read more)